using System;

namespace Silky.Core.Extensions
{
    public static class DateTimeExtensions
    {
        /// <summary>
        /// 将 DateTime 转换成 DateTimeOffset
        /// </summary>
        /// <param name="dateTime"></param>
        /// <returns></returns>
        public static DateTimeOffset ConvertToDateTimeOffset(this DateTime dateTime)
        {
            return DateTime.SpecifyKind(dateTime, DateTimeKind.Local);
        }

        /// <summary>
        /// 将 DateTimeOffset 转换成本地 DateTime
        /// </summary>
        /// <param name="dateTime"></param>
        /// <returns></returns>
        public static DateTime ConvertToDateTime(this DateTimeOffset dateTime)
        {
            if (dateTime.Offset.Equals(TimeSpan.Zero))
                return dateTime.UtcDateTime;
            if (dateTime.Offset.Equals(TimeZoneInfo.Local.GetUtcOffset(dateTime.DateTime)))
                return dateTime.ToLocalTime().DateTime;
            else
                return dateTime.DateTime;
        }

        public static long GetTimeSpan(this DateTime time)
        {
            DateTime d = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Local);
            return (long)(time - d).TotalMilliseconds;
        }

        public static long ToLongTicks(this DateTime dt)
        {
            return ((dt.ToUniversalTime().Ticks - 621355968000000000L) / 10000000);
        }

        public static int ToTicks(this DateTime dt)
        {
            return (int)((dt.ToUniversalTime().Ticks - 621355968000000000L) / 10000000);
        }

        public static long MaxTimeSubtract(this DateTime dt)
        {
            return ConvertDateTimeToLong(DateTime.MaxValue) - ConvertDateTimeToLong(dt);
        }

        // DateTime --> long
        public static long ConvertDateTimeToLong(DateTime dt)
        {
            DateTime dtStart = TimeZoneInfo.ConvertTimeToUtc(new DateTime(1970, 1, 1));
            TimeSpan toNow = dt.Subtract(dtStart);
            long timeStamp = toNow.Ticks;
            timeStamp = long.Parse(timeStamp.ToString().Substring(0, timeStamp.ToString().Length - 4));
            return timeStamp;
        }

        public static DateTime TimeToRequestPatern(this DateTime dt)
        {
            return Convert.ToDateTime(dt.ToString("yyyy-MM-ddTHH:mm:ss.fffffff+08:00"));
        }

        /// <summary>
        /// 转化时间获得零点凌晨的值
        /// </summary>
        /// <param name="dt"></param>
        /// <returns></returns>
        public static DateTime GetCurEarlyDateTime(this DateTime dt)
        {
            return DateTime.Parse(dt.ToString("yyyy-MM-dd 00:00:00"));
        }

        /// <summary>
        /// 转化时间获得零点凌晨的值
        /// </summary>
        /// <param name="dt"></param>
        /// <returns></returns>
        public static DateTime GetCurLateDateTime(this DateTime dt)
        {
            return DateTime.Parse(dt.ToString("yyyy-MM-dd 23:59:59"));
        }

        /// <summary>
        /// 获取当前时间
        /// </summary>
        public static DateTime Now
        {
            get
            {
                return DateTime.UtcNow.AddHours(DateTimeConstant.TimeZone);
            }
        }

        /// <summary>
        /// 获取当前时间的时间戳(毫秒
        /// </summary>
        /// <returns>当前时间的时间戳</returns>
        public static long GetTimeStampNow()
        {
            DateTime startTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
            return (long)(DateTime.UtcNow - startTime).TotalMilliseconds;
        }

        /// <summary>
        /// 获取时间的时间戳(秒
        /// </summary>
        /// <returns>当前时间的时间戳</returns>
        public static long GetTimeStampSeconds(this DateTime dateTime)
        {
            DateTime startTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
            return (long)(dateTime.ToUniversalTime() - startTime).TotalSeconds;
        }

        /// <summary>
        /// 将时间转为时间戳
        /// </summary>
        /// <param name="time"></param>
        /// <returns>时间戳</returns>
        public static long GetTimeStamp(DateTime time)
        {
            DateTime startTime = new DateTime(1970, 1, 1, 0, 0, 0, time.Kind);
            return (long)(time.AddHours(DateTimeConstant.TimeZone * -1) - startTime).TotalMilliseconds;
        }

        /// <summary>
        /// 将时间戳转为时间
        /// </summary>
        /// <param name="totalMilliseconds"></param>
        /// <returns>时间</returns>
        public static DateTime ToTime(long totalMilliseconds)
        {
            var start = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
            return start.AddMilliseconds(totalMilliseconds).AddHours(DateTimeConstant.TimeZone);
        }

        /// <summary>
        /// 获取当天的最小时间
        /// </summary>
        /// <param name="dateTime"></param>
        /// <returns>当天的最小时间</returns>
        public static DateTime GetTodayMinTime(DateTime dateTime)
        {
            return dateTime.Date;
        }

        /// <summary>
        /// 获取当天的明天的最小时间
        /// </summary>
        /// <param name="dateTime"></param>
        /// <returns>当天的明天的最小时间</returns>
        public static DateTime GetTommowMinTime(DateTime dateTime)
        {
            return dateTime.Date.AddDays(1);
        }

        /// <summary>
        /// 将时间转为UTC时间
        /// </summary>
        /// <param name="dateTime">要转换的时间</param>
        /// <returns>UTC时间</returns>
        public static DateTime ToUniversalTime(DateTime dateTime)
        {
            if (dateTime == DateTime.MinValue)
            {
                return DateTime.SpecifyKind(DateTime.MinValue, DateTimeKind.Utc);
            }
            else if (dateTime == DateTime.MaxValue)
            {
                return DateTime.SpecifyKind(DateTime.MaxValue, DateTimeKind.Utc);
            }
            else
            {
                return dateTime.AddHours(DateTimeConstant.TimeZone * -1);
            }
        }

        public static string ToDefaultFormat(DateTime dateTime)
        {
            return ToFormat(dateTime, DateTimeConstant.DefaultFormat);
        }

        public static string ToDefaultFormat(DateTime? dateTime)
        {
            return ToFormat(dateTime, DateTimeConstant.DefaultFormat);
        }

        public static string ToFormat(DateTime dateTime, string format)
        {
            return dateTime.ToString(format);
        }

        public static string ToFormat(DateTime? dateTime, string format)
        {
            if (dateTime.HasValue)
            {
                return dateTime.Value.ToString(format);
            }
            return string.Empty;
        }
    }

    public class DateTimeConstant
    {
        public static string DefaultFormat { get; private set; } = "yyyy-MM-dd HH:mm:sss";

        public static int TimeZone { get; private set; } = 8;

        //internal static void Update(NetZeroDateTimeOptions NetZeroDateTimeOptions)
        //{
        //    DefaultFormat = NetZeroDateTimeOptions.DefaultTimeFormat;
        //    TimeZone = NetZeroDateTimeOptions.TimeZone;
        //}
    }
}